#include "pubmedgenomelocaldatabaseinterface.h"

//TO DO:  delete not working

PubMedGenomeLocalDatabaseInterface::PubMedGenomeLocalDatabaseInterface( QObject* parent )
    : GenomeDatabaseInterface( parent )
{

    createDatabase();
    count = 0;
    //create the genome elt db

    //create the contig db

    if(DISPLAY_MODE == WALL_MODE )
        numToDisplay = 1000;
    else
        numToDisplay = 200;
}

PubMedGenomeLocalDatabaseInterface::PubMedGenomeLocalDatabaseInterface( QString dbName, QObject* parent )
    : GenomeDatabaseInterface( parent )
{

    createDatabase(dbName);
    count = 0;
    //create the genome elt db

    //create the contig db

    if(DISPLAY_MODE == WALL_MODE )
        numToDisplay = 600;//1000;
    else
        numToDisplay = 200;
}

bool PubMedGenomeLocalDatabaseInterface::createDatabase()
{
     db = QSqlDatabase::addDatabase("QSQLITE");
     db.setDatabaseName(QDir::homePath()+"/genomeData.db");
     //db.setDatabaseName( QDir::homePath()+ "/bigGenomeData.db" );
        if (!db.open()) {
            qDebug() << "DATABASE NOT CREATED" << endl;
            return false;
        }

        //else... worked!
        qDebug() << "Database created" << endl;

        //OVERWRITE EXISTING TABLES ... TO DO :  consider whether this should stay
        bool hasGenomeElements = false;
        if( db.tables().contains( "genomeElements" ) )
        {
             QSqlQuery query;
            query.exec("drop table genomeElements");
            //hasGenomeElements = true;
        }
        bool hasContigs = false;
        if( db.tables().contains( "contigs" ) )
        {
             QSqlQuery query;
             query.exec("drop table contigs");
            //hasContigs = true;
        }

        //------create genome element table
        if( !hasGenomeElements )
        {
            QSqlQuery query;
            bool worked = query.exec("create table genomeElements ( dbid integer primary key, seqid varchar(100), source varchar(20), type varchar(20), start integer, stop integer, posStrand varchar(1), parentContigId varchar(100), hasCluster varchar(1), clusterId varchar(100), hasSpecies varchar(1), species varchar(100), id varchar(100), name varchar(100), product varchar(100), parentElement varchar(100) )");
            if( !worked )
            {
                qDebug() << "******************CREATE GENOME ELEMENTS TABLE FAILED****************" << endl;
                qDebug() << query.lastError().text() << endl;

            }
            else
                qDebug() << "genomeElement table created " << endl;

            QSqlQuery q("select * from genomeElements LIMIT 0, 0"); //don't actually select anything but get a reference to the record set

            QSqlRecord rec = q.record();
            for (int i=0; i<rec.count(); i++)
              qDebug() << rec.fieldName(i) << endl;
        }
        //------create contig table
        if( !hasContigs )
        {
            QSqlQuery query2;
            bool worked = query2.exec("create table contigs ( id integer primary key, contigid varchar(100), length integer, hasSpecies varchar(1), species varchar(100))");
            if( !worked )
            {
                qDebug() << "******************CREATE CONTIG TABLE FAILED****************" << endl;
                qDebug() << query2.lastError().text() << endl;

            }
            else
                qDebug() << "contig table created " << endl;

            QSqlQuery q2("select * from contigs LIMIT 0, 0"); //don't actually select anything but get a reference to the record set

            QSqlRecord rec = q2.record();

            //QStringList fields;

            for (int i=0; i<rec.count(); i++)
              qDebug() << rec.fieldName(i) << endl;
        }


}

bool PubMedGenomeLocalDatabaseInterface::createDatabase(QString dbName)
{
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(dbName);//not just name, path
       if (!db.open()) {
           qDebug() << "DATABASE NOT OPENNED" << endl;
           return false;
       }

       //else... worked!
       qDebug() << "Database openned" << endl;

       //print out entries in gneomeElements db, just to check
       QSqlQuery q("select * from genomeElements LIMIT 0, 0"); //don't actually select anything but get a reference to the record set

       QSqlRecord rec = q.record();
       for (int i=0; i<rec.count(); i++)
         qDebug() << rec.fieldName(i) << endl;

       //------create contig table
       QSqlQuery q2("select * from contigs LIMIT 0, 0"); //don't actually select anything but get a reference to the record set

       rec = q2.record();

       //printout contig db, just to check
       for (int i=0; i<rec.count(); i++)
         qDebug() << rec.fieldName(i) << endl;

}

//Note- because these functions are virtual, must recieve generic data packets and convert
void PubMedGenomeLocalDatabaseInterface::addGenomeElement( GenomeElementDataPacket* d )//QPointer<PubMedGenomeElementDataPacket> dataPacket )
{
    PubMedGenomeElementDataPacket* pd = dynamic_cast<PubMedGenomeElementDataPacket* > (d);
    count ++;

    //qDebug() << "seqid: " << pd->getSeqId() << endl;
    QString seqId = pd->getSeqId();//1
    QString source = pd->getSource();//2
    QString type = pd->getType();//3
    int start = pd->getStart();//4
    int stop = pd->getStop();//5
    QString posStrand = QString(pd->getPosStrand()?"T":"F");//6
    QString parentContigId = pd->getParentContigId();//7
    QString hasCluster = QString(pd->getHasCluster()?"T":"F");//8
    //qDebug() << pd->getHasCluster() << " " << hasCluster << endl;
    QString clusterId = pd->getClusterId();//9
    QString hasSpecies = QString(pd->getHasSpecies()?"T":"F");//10
    QString species = pd->getSpecies();//11
    QString id = pd->getId();//12
    QString name = pd->getName();//13
    QString product = pd->getProduct();//14
    QString parentElement = pd->getParentElement();//15


    QSqlQuery query;
    bool worked = query.exec(QString( "insert into genomeElements values(NULL, '%1', '%2', '%3', %4, %5, '%6', '%7', '%8', '%9', '%10', '%11', '%12', '%13', '%14', '%15')")
                             .arg( seqId ).arg(source).arg(type).arg(start).arg(stop).arg(posStrand)
                             .arg(parentContigId).arg(hasCluster).arg(clusterId).arg(hasSpecies).arg(species)
                             .arg(id).arg(name).arg(product).arg(parentElement) );

     if( !worked )
     {
         qDebug() << "QUERY FAILED " <<  query.lastInsertId() << endl;
         qDebug() << query.lastError().text() << endl;
         failedCount++;
     }
     else //if( count < 2 )
     {
         //qDebug() << "add succeeded " << query.lastInsertId() << endl;
         succeededCount++;
     }

    //if parent contig not added, add it

     //regularly commit transaction
     if( count % 100000 == 0 )
     {
         commitTransaction();
         beginTransaction();
     }
}

//Note- because these functions are virtual, must recieve generic data packets and convert
void PubMedGenomeLocalDatabaseInterface::addGenomeElementThenDeleteIt( GenomeElementDataPacket* dataPacket )//QPointer<PubMedGenomeElementDataPacket> dataPacket )
{
    addGenomeElement( dataPacket );
    delete dataPacket;
}

void PubMedGenomeLocalDatabaseInterface::batchAdd( QList< QPointer<GenomeElementDataPacket> > dataPackets )
{
    db.transaction(); //begin transaction

    for(int i = 0; i < dataPackets.size(); i++ )//for all contig data packets
    {
        //for( int j = 0; j < dataPackets[i]->numOfGenomeElements(); j++ )//for all genome elts in those contigs
            addGenomeElement( dataPackets[i].data() );//add to db
    }

    bool worked = db.commit();//commit transaction
    if( !worked )
    {
        qDebug() << "**** COMMIT FAILED ****" << endl;
        qDebug() << db.lastError().text() << endl;
    }
    else
    {
        qDebug() << "Batch add: DB add succeeded" << endl;
        int numRows = 0;
        QSqlQuery q;
        bool worked = q.exec("SELECT COUNT(*) from genomeElements");
        if( worked && q.isActive() && q.isSelect() )
            numRows = q.first();

        qDebug() << "Number of rows= " << numRows << endl;
        qDebug() << "Count= " << count << "Succeeded count = " << succeededCount << "Failed count = " << failedCount << endl;

    }

}

void PubMedGenomeLocalDatabaseInterface::batchAddThenDelete( QList< QPointer<GenomeElementDataPacket> > dataPackets  )
{
    db.transaction(); //begin transaction

    int numElts = 1000;//dataPackets.size();
    if( numElts > dataPackets.size() )
        numElts = dataPackets.size();
    for(int i = 0; i < numElts; i++ )
    {
        qDebug() << "adding" << endl;
        addGenomeElement( dataPackets.first() );//add to db
        delete (dataPackets.takeAt(0).data());
    }

    dataPackets.clear();

    bool worked = db.commit();//commit transaction
    if( !worked )
    {
        qDebug() << "**** COMMIT FAILED ****" << endl;
        qDebug() << db.lastError().text() << endl;
    }
    else
    {
        qDebug() << "DB add succeeded" << endl;
    }

}

void PubMedGenomeLocalDatabaseInterface::beginTransaction()
{
    db.transaction(); //begin transaction
}

void PubMedGenomeLocalDatabaseInterface::commitTransaction()
{
    bool worked = db.commit();//commit transaction
    if( !worked )
    {
        qDebug() << "**** COMMIT FAILED ****" << endl;
        qDebug() << db.lastError().text() << endl;
    }
    else
    {
        qDebug() << "Commit transaction succeeded: " << endl;
        int numRows = 0;
        QSqlQuery q;
        bool worked = q.exec("SELECT COUNT(*) from genomeElements");
        if( worked && q.isActive() && q.isSelect() )
            numRows = q.first();

        qDebug() << "Number of rows= " << numRows << endl;
        qDebug() << "Count= " << count << "Succeeded count = " << succeededCount << "Failed count = " << failedCount << endl;

    }
}

//----------------CONTIGS-------------------
void PubMedGenomeLocalDatabaseInterface::addContig( QPointer< ContigDataPacket> dataPacket  )
{
    contigCount ++;

    QString contigId = dataPacket->getContigId();
    int length = dataPacket->getLength();
    bool hasSpecies = dataPacket->getHasSpecies();
    QString species = dataPacket->getSpecies();

    QSqlQuery query;
    bool worked = query.exec(QString( "insert into contigs values(NULL, '%1', %2, '%3', '%4')" ) //, '%3', %4, %5, '%6', '%7', '%8', '%9', '%10', '%11', '%12', '%13', '%14', '%15')")
                             .arg( contigId ).arg(length).arg(hasSpecies).arg(species));

     if( !worked )
     {
         qDebug() << "CONTIG QUERY FAILED " <<  query.lastInsertId() << endl;
         qDebug() << query.lastError().text() << endl;
         contigFailedCount++;
     }
     else //if( count < 2 )
     {
         //qDebug() << "add succeeded " << query.lastInsertId() << endl;
         contigSucceededCount++;
     }

     //ADD GENOME ELEMENTS
     for(int i = 0 ; i < dataPacket->numOfGenomeElements(); i++ )
     {
         addGenomeElement( dataPacket->getGenomeElementDataPacket(i) );
     }

    //if parent contig not added, add it

     //regularly commit transaction
//     if( count % 100000 == 0 )
//     {
//         commitTransaction();
//         beginTransaction();
//     }
}

void PubMedGenomeLocalDatabaseInterface::addContigThenDeleteIt( QPointer< ContigDataPacket> dataPacket  )
{
    contigCount ++;

    QString contigId = dataPacket->getContigId();
    int length = dataPacket->getLength();
    QString hasSpecies = dataPacket->getHasSpecies() ? "T":"F";
    QString species = dataPacket->getSpecies();

    QSqlQuery query;
    bool worked = query.exec(QString( "insert into contigs values(NULL, '%1', %2, '%3', '%4')" ) //, '%3', %4, %5, '%6', '%7', '%8', '%9', '%10', '%11', '%12', '%13', '%14', '%15')")
                             .arg( contigId ).arg(length).arg(hasSpecies).arg(species));

     if( !worked )
     {
         qDebug() << "CONTIG QUERY FAILED " <<  query.lastInsertId() << endl;
         qDebug() << query.lastError().text() << endl;
         contigFailedCount++;
     }
     else //if( count < 2 )
     {
         //qDebug() << "add succeeded " << query.lastInsertId() << endl;
         contigSucceededCount++;
     }

     //ADD GENOME ELEMENTS
     for(int i = 0 ; i < dataPacket->numOfGenomeElements(); i++ )
     {
         addGenomeElement( dataPacket->getGenomeElementDataPacket(i) );
     }

     //delete dataPacket;
    //if parent contig not added, add it

     //regularly commit transaction
//     if( count % 100000 == 0 )
//     {
//         commitTransaction();
//         beginTransaction();
//     }
}

void PubMedGenomeLocalDatabaseInterface::batchAdd( QList< QPointer< ContigDataPacket> > dataPackets )
{
    db.transaction(); //begin transaction

    for(int i = 0; i < dataPackets.size(); i++ )//for all contig data packets
    {
        //for( int j = 0; j < dataPackets[i]->numOfGenomeElements(); j++ )//for all genome elts in those contigs
            addContig( dataPackets[i].data() );//add to db
    }

    bool worked = db.commit();//commit transaction
    if( !worked )
    {
        qDebug() << "**** COMMIT FAILED ****" << endl;
        qDebug() << db.lastError().text() << endl;
    }
    else
    {
        qDebug() << "Batch add: DB add succeeded" << endl;
        int numRows = 0;
        QSqlQuery q;
        bool worked = q.exec("SELECT COUNT(*) from genomeElements");
        if( worked && q.isActive() && q.isSelect() )
            numRows = q.first();

        qDebug() << "Number of rows= " << numRows << endl;
        qDebug() << "Count= " << count << "Succeeded count = " << succeededCount << "Failed count = " << failedCount << endl;

    }
}

void PubMedGenomeLocalDatabaseInterface::batchAddThenDelete(QList< QPointer< ContigDataPacket> > dataPackets  )
{
    db.transaction(); //begin transaction

    int numElts = 1000;//dataPackets.size();
    if( numElts > dataPackets.size() )
        numElts = dataPackets.size();
    for(int i = 0; i < numElts; i++ )
    {
        qDebug() << "adding" << endl;
        addContig( dataPackets.first() );//add to db
        delete (dataPackets.takeAt(0).data());
    }

    dataPackets.clear();

    bool worked = db.commit();//commit transaction
    if( !worked )
    {
        qDebug() << "**** COMMIT FAILED ****" << endl;
        qDebug() << db.lastError().text() << endl;
    }
    else
    {
        qDebug() << "DB add succeeded" << endl;
    }

}


//QList< QPointer<ContigDataPacket> > PubMedGenomeLocalDatabaseInterface::getSortedByLength(bool longToShort)
//{
//   QList< QPointer <ContigDataPacket>  > toReturn;
//   qDebug() << "Getting sorted by length " << endl;

//   //get contigs
//   if( longToShort )
//   {
//        QSqlQuery query("SELECT * FROM contigs ORDER BY length DESC");
//        int contigIdField = query.record().indexOf("contigid");
//        int lengthField = query.record().indexOf("length");
//        int count = 0;
//        while (query.next() && count < 1000) {
//            count++;
//            QString contigId = query.value(contigIdField).toString();
//            int length = query.value(lengthField).toInt();
//            qDebug() << "getting sorted: " << count << " " << contigId << " " << length << endl;

//            toReturn << new ContigDataPacket(contigId);

//        }
//   }
//   else //short to long
//   {
//        QSqlQuery query("SELECT * FROM contigs ORDER BY length ASC");
//        int contigIdField = query.record().indexOf("contigid");
//        int lengthField = query.record().indexOf("length");
//        int count = 0;
//        query.setForwardOnly(); //only moving forward
//        while (query.next() && count < 1000) {//loop through all, or until 1000
//            count++;
//            QString contigId = query.value(contigIdField).toString();
//            int length = query.value(lengthField).toInt();
//            qDebug() << "getting sorted: " << count << " " << contigId << " " << length << endl;

//            ContigDataPacket* cdp = new ContigDataPacket(contigId);//add to list
//            fillContigWithDataPackets(cdp );

//            //toReturn <<
//        }
//   }

//   //add genome elements to the contig
//   int seqIdIdx;
//   int sourceIdx;
//   int typeIdx;
//   int startIdx;
//   int stopIdx;
//   int posStrandIdx;
//   int parentContigIdIdx;
//   int hasClusterIdx;
//   int clusterIdIdx;
//   int hasSpeciesIdx;
//   int speciesIdx;
//   int idIdx;
//   int nameIdx;
//   int productIdx;
//   int parentElementIdx;

//   for(int i = 0 ; i < toReturn.size(); i++ )
//   {
//       ContigDataPacket* c = toReturn[i];

//   }

//   return toReturn;
//}

void PubMedGenomeLocalDatabaseInterface::getSortedByLength(QList<QPointer<ContigDataPacket> >& contigDataPackets, QList<QPointer<GenomeElementDataPacket> >& genomeElementDataPackets, bool longToShort)
{
    qDebug() << "Sorting contigs " << endl;

    QHash< QString, QPointer<ContigDataPacket> > contigHT;

    //SETUP QUERY
    QString theQuery = "SELECT * FROM contigs ORDER BY length ";
    if( longToShort )
    {
        theQuery.append("DESC");//descending
    }
    else //shortToLong
    {
        theQuery.append("ASC");//ascending
    }

    //RUN QUERY
    QSqlQuery query;
    bool worked = query.exec(theQuery);
    if( ! worked )
    {
        qDebug() << "contig sort failed " << query.lastError() << endl;
        return;
    }
    //query.setForwardOnly(true);//only looping forward  CRASHES
    int contigIdField = query.record().indexOf("contigid");
    int lengthField = query.record().indexOf("length");
    int hasSpeciesField = query.record().indexOf("hasSpecies");
    int speciesField = query.record().indexOf("species");
    int count = 0;
    int geCount = 0;
    QString theGEQuery1 = "SELECT * FROM genomeElements WHERE parentContigId = "; //will build this string
    QString theGEQuery2 = "SELECT * FROM genomeElements WHERE parentContigId = ";//need second one so will execute
    while (query.next() && count < numToDisplay) { //while contigs remain, or until 1000, read query output
        count++;
        geCount = 0;
        QString contigId = query.value(contigIdField).toString();
        int length = query.value(lengthField).toInt();
        bool hasSpecies = query.value(hasSpeciesField).toString().compare("T")?false:true;
        QString species = query.value(speciesField).toString();

        qDebug() << "getting sorted: " << count << " " << contigId << " " << length << endl;
        ContigDataPacket* c = new ContigDataPacket(contigId, hasSpecies, species); //create contig data packet
        if( count == 1 )//if first elt
            theGEQuery1.append( "'").append(contigId ).append("'");
        else if( count < numToDisplay/2 )
            theGEQuery1.append( " OR parentContigId = '" ) .append(contigId ).append("'");
        else if ( count == numToDisplay/2 )
            theGEQuery2.append( "'").append(contigId ).append("'");
        else
            theGEQuery2.append( " OR parentContigId = '" ) .append(contigId ).append("'");

        contigDataPackets << c; //add contig to list
        contigHT.insert(contigId, c);
    }//end loop through sorted contigs

    //-------------------------------

    qDebug() << "theGEQuery = " << theGEQuery1 << endl;

    QSqlQuery geQuery1;
    worked = geQuery1.exec(theGEQuery1);
    if(!worked)
    {
        qDebug() << "sort genomeelt query failed " << geQuery1.lastError() << endl;
        return;
    }

    //get idxs
    int seqidIdx = geQuery1.record().indexOf("seqid");
    int sourceIdx =  geQuery1.record().indexOf("source");
    int typeIdx =  geQuery1.record().indexOf("type");
    int startIdx = geQuery1.record().indexOf("start");
    int stopIdx =  geQuery1.record().indexOf("stop");
    int posStrandIdx =  geQuery1.record().indexOf("posStrand");
    int parentContigIdIdx = geQuery1.record().indexOf("parentContigId");//not really nec... but whatever
    int hasClusterIdx = geQuery1.record().indexOf("hasCluster");
    int clusterIdIdx = geQuery1.record().indexOf("clusterId");
    int hasSpeciesIdx = geQuery1.record().indexOf("hasSpecies");
    int speciesIdx = geQuery1.record().indexOf("species");
    int idIdx = geQuery1.record().indexOf("id");
    int nameIdx = geQuery1.record().indexOf("name");
    int productIdx = geQuery1.record().indexOf("product");
    int parentElementIdx = geQuery1.record().indexOf("parentElement");
    while ( geQuery1.next() )
    {
        PubMedGenomeElementDataPacket* gdp
                = new PubMedGenomeElementDataPacket( geQuery1.value(seqidIdx).toString(),
                                                     geQuery1.value(sourceIdx).toString(),
                                                     geQuery1.value(typeIdx).toString(),
                                                     geQuery1.value(startIdx).toInt(),
                                                     geQuery1.value(stopIdx).toInt(),
                                                     geQuery1.value(posStrandIdx).toString().compare("T")?false:true,
                                                     geQuery1.value(parentContigIdIdx).toString(),
                                                     geQuery1.value(hasClusterIdx).toString().compare("T")?false:true,
                                                     geQuery1.value(clusterIdIdx).toString(),
                                                     geQuery1.value(hasSpeciesIdx).toString().compare("T")?false:true,
                                                     geQuery1.value(speciesIdx).toString(),
                                                     geQuery1.value(idIdx).toString(),
                                                     geQuery1.value(nameIdx).toString(),
                                                     geQuery1.value(productIdx).toString(),
                                                     geQuery1.value(parentElementIdx).toString()
                                                     );
        //contigDataPackets[i]->addGenomeElement(gdp); //add genomeEltDataPacket to contig
        contigHT.value(gdp->getParentContigId())->addGenomeElement(gdp);
        genomeElementDataPackets << gdp; //add genomeEltDataPacket to list

    }//end loop through genome elements

//-------------------

    qDebug() << "theGEQuery2 = " << theGEQuery2 << endl;

    QSqlQuery geQuery2;
    worked = geQuery2.exec(theGEQuery2);
    if(!worked)
    {
        qDebug() << "sort genomeelt query failed " << geQuery2.lastError() << endl;
        return;
    }

    //get idxs
    seqidIdx = geQuery2.record().indexOf("seqid");
    sourceIdx =  geQuery2.record().indexOf("source");
    typeIdx =  geQuery2.record().indexOf("type");
    startIdx = geQuery2.record().indexOf("start");
    stopIdx =  geQuery2.record().indexOf("stop");
    posStrandIdx =  geQuery2.record().indexOf("posStrand");
    parentContigIdIdx = geQuery2.record().indexOf("parentContigId");//not really nec... but whatever
    hasClusterIdx = geQuery2.record().indexOf("hasCluster");
    clusterIdIdx = geQuery2.record().indexOf("clusterId");
    hasSpeciesIdx = geQuery2.record().indexOf("hasSpecies");
    speciesIdx = geQuery2.record().indexOf("species");
    idIdx = geQuery2.record().indexOf("id");
    nameIdx = geQuery2.record().indexOf("name");
    productIdx = geQuery2.record().indexOf("product");
    parentElementIdx = geQuery2.record().indexOf("parentElement");
    while ( geQuery2.next() )
    {
        PubMedGenomeElementDataPacket* gdp
                = new PubMedGenomeElementDataPacket( geQuery2.value(seqidIdx).toString(),
                                                     geQuery2.value(sourceIdx).toString(),
                                                     geQuery2.value(typeIdx).toString(),
                                                     geQuery2.value(startIdx).toInt(),
                                                     geQuery2.value(stopIdx).toInt(),
                                                     geQuery2.value(posStrandIdx).toString().compare("T")?false:true,
                                                     geQuery2.value(parentContigIdIdx).toString(),
                                                     geQuery2.value(hasClusterIdx).toString().compare("T")?false:true,
                                                     geQuery2.value(clusterIdIdx).toString(),
                                                     geQuery2.value(hasSpeciesIdx).toString().compare("T")?false:true,
                                                     geQuery2.value(speciesIdx).toString(),
                                                     geQuery2.value(idIdx).toString(),
                                                     geQuery2.value(nameIdx).toString(),
                                                     geQuery2.value(productIdx).toString(),
                                                     geQuery2.value(parentElementIdx).toString()
                                                     );
        //contigDataPackets[i]->addGenomeElement(gdp); //add genomeEltDataPacket to contig
        contigHT.value(gdp->getParentContigId())->addGenomeElement(gdp);
        genomeElementDataPackets << gdp; //add genomeEltDataPacket to list

    }//end loop through genome elements

}

void PubMedGenomeLocalDatabaseInterface::getContigsWithCluster(QString clusterId, QList<QPointer<ContigDataPacket> > & contigDataPackets, QList<QPointer<GenomeElementDataPacket> > & genomeElementDataPackets)
{
    //FIGURE OUT THE CONTIGS THAT CONTAIN THOSE GENES...
    QSqlQuery clusterQuery;
    clusterQuery.exec( QString("SELECT DISTINCT parentContigId FROM genomeElements WHERE clusterId = '%1' LIMIT 0, %2").arg(clusterId).arg(numToDisplay) );//get genes w this cluster id

    //now build contig query, by getting parent contig id's associated with these genome elements
    QString contigQueryStr = "SELECT * FROM contigs WHERE contigId = "; //will build this string    while(geneQuery.next())
    QString geneQueryStr = "SELECT * FROM genomeElements WHERE parentContigId = ";
    bool first = true;
    while( clusterQuery.next() )
    {
        QString contigId =  clusterQuery.value(0).toString();
        if( first )//if first elt
        {
            contigQueryStr.append( "'").append(contigId ).append("'");
            geneQueryStr.append( "'").append(contigId ).append("'");
            first = false;
        }
        else
        {
            contigQueryStr.append( " OR contigId = '" ) .append(contigId ).append("'");
            geneQueryStr.append( " OR parentContigId = '" ) .append(contigId ).append("'");
        }
    }//done building query strings

    //first get contig data packets
    QSqlQuery contigQuery;
    bool worked = contigQuery.exec( contigQueryStr );
    if( !worked )
    {
        qDebug() << "contig query failed in get contigs w cluster " << endl;
        return;
    }

    int contigIdField = contigQuery.record().indexOf("contigid");
    int lengthField = contigQuery.record().indexOf("length");
    int hasSpeciesField = contigQuery.record().indexOf("hasSpecies");
    int speciesField = contigQuery.record().indexOf("species");

    QHash< QString, QPointer<ContigDataPacket> > contigHT;
    int count = 0;
    while( contigQuery.next() && count < numToDisplay )
    {
        count++;
        QString contigId = contigQuery.value(contigIdField).toString();
        int length = contigQuery.value(lengthField).toInt();
        bool hasSpecies = contigQuery.value(hasSpeciesField).toString().compare("T")?false:true;
        QString species = contigQuery.value(speciesField).toString();

        ContigDataPacket* c = new ContigDataPacket(contigId, hasSpecies, species); //create contig data packet
        contigDataPackets << c; //add contig to list
        contigHT.insert(contigId, c);//add to hash table
    }

    //then get genome element data packets
    QSqlQuery geneQuery;
    worked = geneQuery.exec(geneQueryStr);
    if(!worked)
    {
        qDebug() << "sort genomeelt query failed " << geneQuery.lastError() << endl;
        return;
    }

    //get idxs
    int seqidIdx = geneQuery.record().indexOf("seqid");
    int sourceIdx =  geneQuery.record().indexOf("source");
    int typeIdx =  geneQuery.record().indexOf("type");
    int startIdx = geneQuery.record().indexOf("start");
    int stopIdx =  geneQuery.record().indexOf("stop");
    int posStrandIdx =  geneQuery.record().indexOf("posStrand");
    int parentContigIdIdx = geneQuery.record().indexOf("parentContigId");//not really nec... but whatever
    int hasClusterIdx = geneQuery.record().indexOf("hasCluster");
    int clusterIdIdx = geneQuery.record().indexOf("clusterId");
    int hasSpeciesIdx = geneQuery.record().indexOf("hasSpecies");
    int speciesIdx = geneQuery.record().indexOf("species");
    int idIdx = geneQuery.record().indexOf("id");
    int nameIdx = geneQuery.record().indexOf("name");
    int productIdx = geneQuery.record().indexOf("product");
    int parentElementIdx = geneQuery.record().indexOf("parentElement");
    while ( geneQuery.next() )
    {
        PubMedGenomeElementDataPacket* gdp
                = new PubMedGenomeElementDataPacket( geneQuery.value(seqidIdx).toString(),
                                                     geneQuery.value(sourceIdx).toString(),
                                                     geneQuery.value(typeIdx).toString(),
                                                     geneQuery.value(startIdx).toInt(),
                                                     geneQuery.value(stopIdx).toInt(),
                                                     geneQuery.value(posStrandIdx).toString().compare("T")?false:true,
                                                     geneQuery.value(parentContigIdIdx).toString(),
                                                     geneQuery.value(hasClusterIdx).toString().compare("T")?false:true,
                                                     geneQuery.value(clusterIdIdx).toString(),
                                                     geneQuery.value(hasSpeciesIdx).toString().compare("T")?false:true,
                                                     geneQuery.value(speciesIdx).toString(),
                                                     geneQuery.value(idIdx).toString(),
                                                     geneQuery.value(nameIdx).toString(),
                                                     geneQuery.value(productIdx).toString(),
                                                     geneQuery.value(parentElementIdx).toString()
                                                     );
        contigHT.value(gdp->getParentContigId())->addGenomeElement(gdp);
        genomeElementDataPackets << gdp; //add genomeEltDataPacket to list

    }//end loop through genome elements

}

void PubMedGenomeLocalDatabaseInterface::getStringMatches(QString searchFragment, QList<QPointer<ContigDataPacket> > & contigDataPackets, QList<QPointer<GenomeElementDataPacket> > & genomeElementDataPackets)
{

    //FIGURE OUT THE CONTIGS THAT CONTAIN THOSE GENES...
    QSqlQuery productMatchQuery;
    //stringMatchQuery.exec( QString("SELECT product FROM genomeElements WHERE product = %'%1'%").arg(clusterId) );//get genes w this cluster id

    QStringList toReturn;

    qDebug() << QString("SELECT DISTINCT parentContigId FROM genomeElements WHERE product like '%%1%' LIMIT 0, %2").arg(searchFragment).arg(numToDisplay) << endl;
    productMatchQuery.exec( QString("SELECT DISTINCT parentContigId FROM genomeElements WHERE product like '%%1%' LIMIT 0, %2").arg(searchFragment).arg(numToDisplay) );//get genes w this cluster id
//    while( stringMatchQuery.next() )
//    {
//        toReturn << stringMatchQuery.value(0).toString() << endl;

//    }//done building query strings

//    return toReturn;


    //now build contig query, by getting parent contig id's associated with these genome elements
    QString contigQueryStr = "SELECT * FROM contigs WHERE contigId = "; //will build this string    while(geneQuery.next())
    QString geneQueryStr = "SELECT * FROM genomeElements WHERE parentContigId = ";
    bool first = true;
    while( productMatchQuery.next() )
    {
        QString contigId =  productMatchQuery.value(0).toString();
        if( first )//if first elt
        {
            contigQueryStr.append( "'").append(contigId ).append("'");
            geneQueryStr.append( "'").append(contigId ).append("'");
            first = false;
        }
        else
        {
            contigQueryStr.append( " OR contigId = '" ) .append(contigId ).append("'");
            geneQueryStr.append( " OR parentContigId = '" ) .append(contigId ).append("'");
        }
    }//done building query strings

    qDebug() << "Contig Query: " << contigQueryStr << endl;

    //first get contig data packets
    QSqlQuery contigQuery;
    bool worked = contigQuery.exec( contigQueryStr );
    if( !worked )
    {
        qDebug() << "contig query failed in get contigs w cluster " << endl;
        return;
    }

    int contigIdField = contigQuery.record().indexOf("contigid");
    int lengthField = contigQuery.record().indexOf("length");
    int hasSpeciesField = contigQuery.record().indexOf("hasSpecies");
    int speciesField = contigQuery.record().indexOf("species");

    QHash< QString, QPointer<ContigDataPacket> > contigHT;
    int count = 0;
    while( contigQuery.next() && count < numToDisplay )
    {
        count++;
        QString contigId = contigQuery.value(contigIdField).toString();
        int length = contigQuery.value(lengthField).toInt();
        bool hasSpecies = contigQuery.value(hasSpeciesField).toString().compare("T")?false:true;
        QString species = contigQuery.value(speciesField).toString();

        ContigDataPacket* c = new ContigDataPacket(contigId, hasSpecies, species); //create contig data packet
        contigDataPackets << c; //add contig to list
        contigHT.insert(contigId, c);//add to hash table
    }

    //then get genome element data packets
    QSqlQuery geneQuery;
    worked = geneQuery.exec(geneQueryStr);
    if(!worked)
    {
        qDebug() << "sort genomeelt query failed " << geneQuery.lastError() << endl;
        return;
    }

    //get idxs
    int seqidIdx = geneQuery.record().indexOf("seqid");
    int sourceIdx =  geneQuery.record().indexOf("source");
    int typeIdx =  geneQuery.record().indexOf("type");
    int startIdx = geneQuery.record().indexOf("start");
    int stopIdx =  geneQuery.record().indexOf("stop");
    int posStrandIdx =  geneQuery.record().indexOf("posStrand");
    int parentContigIdIdx = geneQuery.record().indexOf("parentContigId");//not really nec... but whatever
    int hasClusterIdx = geneQuery.record().indexOf("hasCluster");
    int clusterIdIdx = geneQuery.record().indexOf("clusterId");
    int hasSpeciesIdx = geneQuery.record().indexOf("hasSpecies");
    int speciesIdx = geneQuery.record().indexOf("species");
    int idIdx = geneQuery.record().indexOf("id");
    int nameIdx = geneQuery.record().indexOf("name");
    int productIdx = geneQuery.record().indexOf("product");
    int parentElementIdx = geneQuery.record().indexOf("parentElement");
    while ( geneQuery.next() )
    {
        PubMedGenomeElementDataPacket* gdp
                = new PubMedGenomeElementDataPacket( geneQuery.value(seqidIdx).toString(),
                                                     geneQuery.value(sourceIdx).toString(),
                                                     geneQuery.value(typeIdx).toString(),
                                                     geneQuery.value(startIdx).toInt(),
                                                     geneQuery.value(stopIdx).toInt(),
                                                     geneQuery.value(posStrandIdx).toString().compare("T")?false:true,
                                                     geneQuery.value(parentContigIdIdx).toString(),
                                                     geneQuery.value(hasClusterIdx).toString().compare("T")?false:true,
                                                     geneQuery.value(clusterIdIdx).toString(),
                                                     geneQuery.value(hasSpeciesIdx).toString().compare("T")?false:true,
                                                     geneQuery.value(speciesIdx).toString(),
                                                     geneQuery.value(idIdx).toString(),
                                                     geneQuery.value(nameIdx).toString(),
                                                     geneQuery.value(productIdx).toString(),
                                                     geneQuery.value(parentElementIdx).toString()
                                                     );
        contigHT.value(gdp->getParentContigId())->addGenomeElement(gdp);
        genomeElementDataPackets << gdp; //add genomeEltDataPacket to list

    }//end loop through genome elements
}

//void  PubMedGenomeLocalDatabaseInterface::fillContigWithDataPackets( ContigDataPacket* cdp)
//{
//    QString cID = c->getContigId();
//    QSqlQuery query( QString("SELECT * FROM genomeElements WHERE parentContigId = '%1' ORDER BY start ASC").arg(cID) );
//    query.setForwardOnly(); //only moving forward

//    //get idxs
//    seqidIdx = query.record().indexOf("seqid");
//    sourceIdx =  query.record().indexOf("source");
//    typeIdx =  query.record().indexOf("type");
//    startIdx = query.record().indexOf("start");
//    stopIdx =  query.record().indexOf("stop");
//    posStrandIdx =  query.record().indexOf("posStrand");
//    parentContigIdIdx = query.record().indexOf("parentContigId");//not really nec... but whatever
//    hasClusterIdx = query.record().indexOf("hasCluster");
//    clusterIdIdx = query.record().indexOf("clusterId");
//    hasSpeciesIdx = query.record().indexOf("hasSpecies");
//    speciesIdx = query.record().indexOf("species");
//    idIdx = query.record().indexOf("id");
//    nameIdx = query.record().indexOf("name");
//    productIdx = query.record().indexOf("product");
//    parentElementIdx = query.record().indexOf("parentElement");

//    //for every contig, make all genome elements
//    while ( query.next() )
//    {
//        PubMedGenomeElementDataPacket* gdp
//                = new PubMedGenomeElementDataPacket( query.value(seqIdIdx).toString(),
//                                                     query.value(sourceIdx).toString(),
//                                                     query.value(typeIdx).toString(),
//                                                     query.value(startIdx).toInt(),
//                                                     query.value(stopIdx).toInt(),
//                                                     query.value(posStrandIdx).toString().compare("T")?true:false,
//                                                     query.value(parentContigIdx).toString(),
//                                                     query.value(hasClusterIdx).toString().compare("T")?true:false,
//                                                     query.value(clusterIdIdx).toString(),
//                                                     query.value(hasSpeciesIdx).toString().compare("T")?true:false,
//                                                     query.value(species).toString(),
//                                                     query.value(idIdx).toString(),
//                                                     query.value(nameIdx).toString(),
//                                                     query.value(productIdx).toString(),
//                                                     query.value(parentIdx).toString()
//                                                     );
//        cdp->addGenomeElement(gdp);
//    }

//}


void PubMedGenomeLocalDatabaseInterface::empty()
{
    qDebug() << "pubmed" << endl;

}
